home *** CD-ROM | disk | FTP | other *** search
/ Cracking 1 / Cracking I..iso / Tools / Ostatní / aPLib v0.26b / examples / 16bit / deppack.nas next >
Encoding:
Text File  |  2001-12-15  |  16.9 KB  |  313 lines

  1. ;;
  2. ;; aPLib compression library  -  the smaller the better :)
  3. ;;
  4. ;; NASM 16bit assembler depacker example
  5. ;;
  6. ;; Copyright (c) 1998-2000 by Joergen Ibsen / Jibz
  7. ;; All Rights Reserved
  8. ;;
  9. ;; -> 16bit by METALBRAIN (metalb@bart.us.es)
  10. ;;
  11.  
  12.                 org     256
  13.  
  14.                 cld                     ;Clear direction flag for safety
  15.                 mov     ah,4ah          ;Modify memory block size (on start,
  16.                                         ; the .COM program is given all free
  17.                                         ; memory, but this could be less than
  18.                                         ; the needed amount (162K). As a nice
  19.                                         ; side effect, we are freeing unused
  20.                                         ; memory, but who cares under DOS?
  21.                 mov     bh,41           ;Number of needed paragraphs
  22.                                         ; (rounded up)
  23.                 int     33              ;Resize
  24.                 jnc     not_error008    ;Continue if no error
  25.                 call    final           ;Exit with message below
  26.                 db      "Not enough memory$"
  27. not_error008    mov     si,129          ;Arguments from PSP start here
  28.                 mov     di,testitnow    ;This will be called quite a few times
  29.                                         ; and later will be used to place
  30.                                         ; variables
  31. space1          call    di              ;Parse...
  32.                 jz      space1          ;Search for non-space
  33.                 dec     si              ;Found: here start infile name
  34.                 mov     dx,si           ;Keep it in DX
  35. space2          call    di              ;Keep parsing
  36.                 jnz     space2          ;Till a space appears
  37.                 mov     [si-1],dh       ;Make infile ASCIIZ
  38. space3          call    di
  39.                 jz      space3          ;Now search a non-space again
  40.                 dec     si              ;Here start outfile name
  41.                 push    si              ;Keep it in stack
  42. space4          lodsb                   ;Final parse
  43.                 cmp     al," "
  44.                 ja      space4          ;Space or below means end of filename
  45.                 mov     [si-1],dh       ;Make ASCIIZ this one too
  46.                 mov     ax,3d00h        ;Function to open infile
  47.                 int     33              ;Open infile
  48.                 jnc     not_error001    ;Continue if no error
  49.                 call    final           ;Exit with message below
  50.                 db "Can't open infile$"
  51. not_error001    stosw
  52.                 mov     dx,tmpname
  53.                 xor     cx,cx
  54.                 mov     ah,3ch
  55.                 int     33              ;Create temporal outfile: "g ok$"
  56.                 jnc     not_error007    ;Continue if no error
  57.                 call    final           ;Exit with message below
  58.                 db "Can't open temporal outfile$"
  59. not_error007    stosw                   ;Store temporal outfile handle
  60.                 xchg    ax,dx           ;And place it in DX
  61.                 xor     ebx,ebx         ;EBX=0
  62.                 pop     si              ;Pop outfile name address from stack
  63.                 mov     bh,8            ;BX=inbuff
  64.                 mov     esp,ebx         ;Set stack before inbuff
  65.                 mov     bx,es           ;Segment
  66.                 add     bh,8            ; +32K
  67.                 imul    eax,ebx,byte 16 ;32 bit start of segment address+32K
  68.                 add     eax,esp         ;EAX=freemem 32 bit address
  69.                 push    si              ;Push again outfile name address
  70.                 push    dx              ;Also store temporal outfile handle
  71.                 mov     dl,128          ;Reset bit counter in DL, and DX=0080h
  72.                 mov     cl,3            ;Set EAX at freemem32, origin32 and
  73.                 rep     stosd           ;  limit32
  74.                 add     [di-2],byte 2   ;Now limit32=freemem32+128K
  75.                 add     [di-7],dx       ;Now origin32=freemem32+32K
  76.                 xchg    eax,edi         ;Set freemem32 at EDI
  77.                 mov     esi,edi         ;And ESI
  78.                                         ;Starting point for DEPACK16
  79.                 push    edi             ;Store freemem32
  80. literal         call    getesi          ;Copy a byte from [esi] to [edi]
  81. putedi_nexttag  call    putedi
  82.                 call    newtest         ;Here EAX=0
  83.                 jmp     short nexttag   ;Decode next tag bits...
  84.  
  85. normalcodepair  xchg    ax,cx           ;High part of distance in AX
  86.                 dec     ax              ;Subtract 1. Min value is 0
  87.                 shl     eax,8           ;EAX=00dddd00h
  88.                 call    getesi          ;Fill distance in AL
  89.                 call    getgamma        ;Take gamma encoded ECX
  90.                 cmp     eax,32000
  91.                 jae     domatch_with_2inc ;Above 31999: ECX+=2
  92.                 cmp     ah,5
  93.                 jae     domatch_with_inc ; 1279<EAX<32000: ECX=+1
  94.                 cmp     ax,byte 127
  95.                 ja      domatch         ;EAX<128: ECX+=2
  96. domatch_with_2inc
  97.                 inc     ecx
  98. domatch_with_inc
  99.                 inc     ecx
  100. domatch         xchg    eax,ebp         ;Store EAX in EBP
  101. domatch_R0      mov     eax,ebp         ;Take EAX from last EBP
  102. domatch_continue
  103.                                         ;Here EAX=match distance
  104.                                         ;     ECX=match lenght
  105.                 push    esi             ;Store current read pointer
  106.                 mov     esi,edi
  107.                 sub     esi,eax         ;ESI=EDI-EAX > origin pointer
  108.                 cmp     esi,[freemem32] ;Test for bad infile #1: Limit crossed
  109.                 jc      near badinfile  ;Exit if error
  110. repmovsb        call    dontread        ;getesi without checking limit
  111.                 call    putedi          ;and with putedi completes the movsb
  112.                 mov     ah,128          ;Here EAX=32768 (in case of writing
  113.                 call    newtest         ;  data, update esi too)
  114.                 loop    repmovsb,ecx    ;Do it ecx times
  115.                 pop     esi             ;Recover read pointer
  116. nexttag         call    getbit          ;Get a bit
  117.                 jnc     literal         ;0: literal, go for it
  118.                 xor     ecx,ecx         ;Clear ECX
  119.                 xor     ax,ax           ;and AX
  120.                 call    getbit          ;Get another bit
  121.                 jnc     codepair        ;10: codepair, go for it
  122.                 call    getbit          ;Get yet another one
  123.                 jnc     shortmatch      ;110: shortmatch
  124.                 inc     cx              ;CX=1
  125.                 mov     al,16           ;Set marker bit
  126. getmorebits     call    getbit          ;Get a bit
  127.                 adc     al,al           ;Set it in AL
  128.                 jnc     getmorebits     ;Do it till marker is out (4 times)
  129.                 jnz     domatch_continue ; 111xxxx > continue, AL has distance
  130.                 jmp     short putedi_nexttag    ;1110000: Put a zero byte
  131.  
  132. codepair        call    getgamma        ;Get gamma encoded first part of
  133.                                         ; distance in CX. Min value is 2
  134.                 dec     cx              ;\Subtract 2, if not zero then
  135.                 loop    normalcodepair  ;/continue with distance
  136.                 push    word domatch_R0 ;Get gamma encoded lenght in ECX then
  137.                                         ; jump to domatch_R0 (use last
  138.                                         ; distance)
  139.  
  140. getgamma        inc     cx              ;First bit is always 1
  141. getgammaloop    call    getbit          ;Get next bit
  142.                 adc     ecx,ecx         ;Put it in ECX
  143.                 call    getbit          ;Get gamma bit
  144.                 jc      getgammaloop    ;If it's 1, continue growing ECX
  145.                 ret
  146.  
  147. shortmatch      call    getesi          ;Get a byte
  148.                 shr     ax,1            ;Distance = AL/2, Lenght in carry flag
  149.                 jz      donedepacking   ;If zero, end packing
  150.                 adc     cx,cx           ;Lenght = 1 or 0
  151.                 jmp     short domatch_with_2inc ; Decode with lenght 2 or 3
  152.  
  153. getbit          add     dl,dl           ;Get a tag bit
  154.                 jnz     stillbitsleft   ;If zero, that bit was the marker, so
  155.                                         ; we must read a new tag byte from
  156.                 xchg    ax,dx           ;\ the infile buffer
  157.                 call    getesi          ; >Emulate mov dl,[esi], inc esi
  158.                 xchg    ax,dx           ;/
  159.                 stc                     ;Carry flag is end marker
  160.                 adc     dl,dl           ;Get first bit and set marker
  161. stillbitsleft   ret                     ;Return with bit read in flag C
  162.  
  163. donedepacking   pop     esi             ;ESI=freemem32
  164.                 pop     bx              ;Get outfile handle
  165.                 sub     edi,esi         ;And here finish DEPACK 16
  166.                                         ;Now edi has the number of depacked
  167.                                         ; bytes left to be written
  168.                 push    ds              ;Preserve data segment
  169.                 mov     ch,080h         ;Write using 32K chunks to enable
  170.                                         ; the sign optimization
  171.                 mov     dx,freemem      ;Flush everything from here to end
  172. more            cmp     edi,ecx
  173.                 ja      notlast         ;If EDI > 32K, write 32K bytes
  174.                 mov     cx,di           ;If EDI < 32K, write EDI bytes
  175. notlast         call    writefile       ;Write chunk
  176.                 mov     ax,ds
  177.                 add     ah,8
  178.                 mov     ds,ax           ;Advance 32K
  179.  
  180.                 sub     edi,ecx         ;Update number of bytes to be written
  181.                 ja      more            ;Above zero, continue writing
  182.                 pop     ds              ;Recover data segment
  183.                 push    ds
  184.                 pop     es              ;Set es=ds
  185.                 pop     dx              ;Get nameout
  186.                 call    close_del       ;Close temporal outfile and try to
  187.                                         ; delete the file named with our
  188.                                         ; outfile name, in case it exists
  189.                 jnc     renameit        ;If that file existed and was deleted,
  190.                                         ; go ahead and rename the temporal one
  191.                 cmp     al,5            ;If it didn't exist, rename it too
  192.                 jz      error002b       ;In case of Access denied, it must
  193.                                         ; be that outfile was protected, so
  194.                                         ; that's an error...
  195. renameit        mov     ah,56h
  196.                 mov     di,dx
  197.                 mov     dx,tmpname
  198.                 int     33              ;Rename temporal outfile to outfile
  199.                 jc      error002        ;Can't open outfile
  200.                 push    word noerr      ;Final message
  201. final           push    ss
  202.                 pop     ds              ;Set a good data segment
  203.                 pop     dx              ;Get message offset
  204. final_dxok      mov     ah,9
  205.                 int     33              ;Show final message
  206.                 int     20h             ;Exit program
  207. writefile       mov     ah,40h
  208.                 int     33              ;Write to temporal outfile
  209.                 jc      error005        ;Can't write
  210.                 dec     ax
  211.                 js      error006        ;Disk is full
  212.                 ret
  213. error002b       push    word err002b    ;Set appropiate message
  214.                 jmp     short rub3      ;Exit erasing temporal file
  215. error002        push    word err002     ;Set appropiate message
  216.                 jmp     short rub4      ;Exit erasing temporal file
  217. error005        push    word err005     ;Set appropiate message
  218.                 jmp     short rub3      ;Exit erasing temporal file
  219. error006        push    word err006     ;Set appropiate message
  220. rub3            mov     dx,tmpname      ;Temporal file name to be erased
  221. rub4            push    word final      ;Return point to exit with error
  222. close_del       mov     ah,3eh
  223.                 int     33              ;Close temporal outfile
  224.                 mov     ah,41h
  225.                 int     33              ;Delete it
  226.                 ret
  227.  
  228. getesi          cmp     esi,[freemem32] ; If esi is at freemem32, we must
  229.                 jnz     dontread        ;load 32k of compressed data
  230.                 pushad                  ;Keep all registers (32bit because
  231.                 mov     ah,3fh          ; DOS function may modify EAX!!!)
  232.                 mov     bx,[handlein]   ;Take infile handle
  233.                 mov     cx,32768        ;Number of bytes
  234.                 mov     dx,inbuff       ;Place to read
  235.                 int     33              ;Read, AX=number of bytes read
  236.                 jc      error003        ;If error, go to exit
  237. noerror003      dec     ax              ;Test for bad infile #2: 0 bytes read
  238.                                         ; (a good infile will finish and won't
  239.                                         ; ask for more data)
  240.                 jns     noerror004      ;No error, continue
  241. badinfile       push    word err004     ;Set appropiate message
  242.                 jmp     short error004
  243. error003        push    word err003     ;Set appropiate message
  244. error004        mov     bx,[handletmp]  ;Get handle to close temporal file
  245.                 jmp     short rub3      ;Exit erasing temporal file
  246. noerror004      popad                   ;Restore all registers
  247.                 sub     esi,32768       ;esi at beginning of buffer again
  248. dontread        push    esi             ;----->Emulates mov al,[esi] in 16 bit
  249.                 pop     bx              ;    /   code (as mov al,[esi] gives
  250.                 pop     bx              ;   /    a nasty fault)
  251.                 ror     bx,4            ;  /
  252.                 mov     es,bx           ; /
  253.                 mov     al,[es:si]      ;/
  254.                 inc     esi             ;Update read pointer
  255.                 ret
  256.  
  257. newtest         cmp     edi,[limit32]   ;Check if we've run out of memory
  258.                 jc      endtest         ;NO: end test
  259.                 pushad                  ;Keep registers
  260.                 mov     dx,freemem
  261.                 mov     cx,32768
  262.                 mov     bx,[handletmp]
  263.                 call    writefile       ;Write 32K of data
  264.                 mov     ecx,edi
  265.                 mov     esi,[origin32]
  266.                 sub     ecx,esi         ;ECX=number of bytes to be moved
  267.                 mov     edi,[freemem32] ;Output data will be moved 32K back
  268. otherrepmovsb   call    getesi          ;  \
  269.                 call    putedi          ;   >Emulates rep movsb
  270.                 loop    otherrepmovsb,ecx ;/
  271.                 popad                   ;Restore registers
  272.                 sub     esi,eax         ;Update read pointer (sub 32K if
  273.                                         ;   we are in the repmovsb loop)
  274.                 mov     ah,128          ;EAX=32K
  275.                 sub     edi,eax         ;Update write pointer
  276. endtest         ret
  277.  
  278. putedi          push    edi             ;----->Emulate mov [edi],al in 16 bit
  279.                 pop     bx              ;    /  code (as mov [edi],al gives
  280.                 pop     bx              ;   /   a nasty fault)
  281.                 ror     bx,4            ;  /
  282.                 mov     es,bx           ; /
  283.                 mov     [es:di],al      ;/
  284.                 inc     edi             ;Update write pointer
  285.                 xor     eax,eax         ;Clear EAX
  286. noerror000      ret
  287. testitnow       lodsb                   ;Parse one byte
  288.                 cmp     al,32           ;Is it space?
  289.                 jnc     noerror000      ;If valid char (above 31), return
  290.                 call    final           ;Exit with message below
  291.                 db "Usage: DEPPACK infile outfile",13,10,10
  292.                 db "infile must be an aPPACKed file",13,10
  293.                 db "wildcards are not allowed",13,10,10
  294.                 db "DEPPACK v0.9 Copyright (c) 1998-2000 by METALBRAIN",13,10
  295.                 db "aPLib v0.26b Copyright (c) 1998-2000 by Jibz, All Rights Reserved$"
  296. err005          db "Can't write temporal outfile$"
  297. err002b         db "Outfile is protected, so...",13,10
  298. err002          db "Can't open outfile$"
  299. err003          db "Can't read from infile$"
  300. err004          db "Bad infile$"
  301. err006          db "Disk full$"
  302. noerr           db "Deppackin"
  303. tmpname         db "g ok$",0
  304.  
  305. handlein        EQU     testitnow
  306. handletmp       EQU     testitnow+2
  307. freemem32       EQU     testitnow+4
  308. origin32        EQU     testitnow+8
  309. limit32         EQU     testitnow+12
  310.                                         ;Stack is between program and 2048
  311. inbuff          EQU     2048            ;Place for 32K infile reading buffer
  312. freemem         EQU     inbuff+32768
  313.